using System.Net;
using System.Net.Sockets;
using Google.Protobuf;

namespace muduoDotNet
{
    /// <summary>
    /// TCP连接状态枚举
    /// </summary>
    public enum TcpConnectionState
    {
        Disconnected,
        Connecting,
        Connected,
        Disconnecting
    }

    /// <summary>
    /// TcpConnection类，代表一个TCP连接
    /// </summary>
    public class TcpConnection : IDisposable
    {
        private readonly EventLoop _loop;
        private readonly string _name;
        private readonly Socket _socket;
        private readonly Channel _channel;
        private readonly Buffer _inputBuffer;
        private readonly Buffer _outputBuffer;
        private TcpConnectionState _state;
        private bool _disposed;
        
        // 协议编解码相关
        private IProtocolCodec? _protocolCodec;
        private IProtocolMessageHandler? _messageHandler;
        private readonly Dictionary<Type, object> _protocolCallbacks;

        public TcpConnection(EventLoop loop, string name, Socket socket)
        {
            _loop = loop ?? throw new ArgumentNullException(nameof(loop));
            _name = name ?? throw new ArgumentNullException(nameof(name));
            _socket = socket ?? throw new ArgumentNullException(nameof(socket));
            _inputBuffer = new Buffer();
            _outputBuffer = new Buffer();
            _state = TcpConnectionState.Connecting;
            _disposed = false;
            
            // 初始化协议支持
            _protocolCallbacks = new Dictionary<Type, object>();
            _protocolCodec = new ProtobufCodec(); // 默认使用protobuf编解码器

            // 注册Socket到管理器
            SocketManager.RegisterSocket(_socket);

            // 创建Channel并设置回调
            _channel = new Channel(loop, socket.Handle.ToInt32());
            _channel.ReadCallback = HandleRead;
            _channel.WriteCallback = HandleWrite;
            _channel.ErrorCallback = HandleError;
        }

        public string Name => _name;
        public TcpConnectionState State => _state;
        public EndPoint LocalEndPoint => _socket.LocalEndPoint;
        public EndPoint RemoteEndPoint => _socket.RemoteEndPoint;
        public EventLoop Loop => _loop;
        
        // 协议相关属性
        public IProtocolCodec? ProtocolCodec
        {
            get => _protocolCodec;
            set => _protocolCodec = value;
        }
        
        public IProtocolMessageHandler? MessageHandler
        {
            get => _messageHandler;
            set => _messageHandler = value;
        }

        // 事件回调
        public Action<TcpConnection> ConnectionCallback { get; set; }
        public Action<TcpConnection, Buffer> MessageCallback { get; set; }
        public Action<TcpConnection> WriteCompleteCallback { get; set; }
        public Action<TcpConnection> CloseCallback { get; set; }

        /// <summary>
        /// 建立连接
        /// </summary>
        public void ConnectEstablished()
        {
            _loop.RunInLoop(() =>
            {
                if (_state == TcpConnectionState.Connecting)
                {
                    _state = TcpConnectionState.Connected;
                    _channel.EnableReading();
                    ConnectionCallback?.Invoke(this);
                }
            });
        }

        /// <summary>
        /// 连接销毁
        /// </summary>
        public void ConnectDestroyed()
        {
            _loop.RunInLoop(() =>
            {
                if (_state == TcpConnectionState.Connected)
                {
                    _state = TcpConnectionState.Disconnected;
                    _channel.DisableAll();
                    CloseCallback?.Invoke(this);
                }
                _channel.Remove();
            });
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="message">要发送的数据</param>
        public void Send(byte[] message)
        {
            if (_state == TcpConnectionState.Connected)
            {
                if (_loop.IsInLoopThread())
                {
                    SendInLoop(message);
                }
                else
                {
                    var messageCopy = new byte[message.Length];
                    System.Buffer.BlockCopy(message, 0, messageCopy, 0, message.Length);
                    _loop.RunInLoop(() => SendInLoop(messageCopy));
                }
            }
        }

        /// <summary>
        /// 发送字符串
        /// </summary>
        /// <param name="message">要发送的字符串</param>
        public void Send(string message)
        {
            var bytes = System.Text.Encoding.UTF8.GetBytes(message);
            Send(bytes);
        }

        /// <summary>
        /// 发送protobuf消息
        /// </summary>
        /// <param name="message">要发送的protobuf消息</param>
        public void SendProtobufMessage(IMessage message)
        {
            if (_protocolCodec == null)
            {
                Logger.Error("Protocol codec is not set, cannot send protobuf message");
                return;
            }

            try
            {
                var encodedData = _protocolCodec.Encode(message);
                Send(encodedData);
                Logger.Debug($"Sent protobuf message: type={message.GetType().Name}, size={encodedData.Length} bytes");
                
                // 更新性能计数器
                PerformanceCounters.AddBytesSent(encodedData.Length);
                PerformanceCounters.UpdateConnectionStats(_name, encodedData.Length, 0);
            }
            catch (Exception ex)
            {
                Logger.Error($"Failed to send protobuf message: {message.GetType().Name}", ex);
                PerformanceCounters.IncrementProtocolExceptions();
                PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
            }
        }

        /// <summary>
        /// 设置协议消息回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="callback">回调函数</param>
        public void SetProtocolMessageCallback<T>(ProtocolMessageCallback<T> callback) where T : class, IMessage
        {
            _protocolCallbacks[typeof(T)] = callback;
        }

        /// <summary>
        /// 移除协议消息回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        public void RemoveProtocolMessageCallback<T>() where T : class, IMessage
        {
            _protocolCallbacks.Remove(typeof(T));
        }

        /// <summary>
        /// 在事件循环线程中发送数据
        /// </summary>
        /// <param name="message">要发送的数据</param>
        private void SendInLoop(byte[] message)
        {
            if (!_loop.IsInLoopThread())
            {
                throw new NetException("SendInLoop should be called in loop thread");
            }

            if (_state == TcpConnectionState.Disconnected)
            {
                Logger.Warning("Disconnected, give up writing");
                return;
            }

            int remaining = message.Length;
            bool faultError = false;

            try
            {
                // 如果输出缓冲区为空，直接尝试发送数据
                if (_outputBuffer.ReadableBytes == 0 && remaining > 0)
                {
                    int bytesWritten = _socket.Send(message, SocketFlags.None);
                    remaining -= bytesWritten;
                    if (remaining == 0 && WriteCompleteCallback != null)
                    {
                        _loop.QueueInLoop(() => WriteCompleteCallback(this));
                    }
                }

                // 如果还有数据未发送，加入输出缓冲区
                if (remaining > 0)
                {
                    _outputBuffer.Append(message.AsSpan(message.Length - remaining, remaining).ToArray());
                    if (!_channel.IsWriting())
                    {
                        _channel.EnableWriting();
                    }
                }
                
                // 更新性能计数器
                PerformanceCounters.AddBytesSent(message.Length - remaining);
                PerformanceCounters.UpdateConnectionStats(_name, message.Length - remaining, 0);
            }
            catch (SocketException ex)
            {
                // 处理非阻塞Socket的EWOULDBLOCK错误
                if (ex.SocketErrorCode == SocketError.WouldBlock ||
                    ex.SocketErrorCode == SocketError.IOPending ||
                    ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
                {
                    // 这些错误是预期的，继续处理
                }
                else
                {
                    Logger.Error($"Socket send error on connection {_name}: {ex.SocketErrorCode}", ex);
                    PerformanceCounters.IncrementNetworkExceptions();
                    PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                    faultError = true;
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"Unexpected error in SendInLoop for connection {_name}", ex);
                PerformanceCounters.IncrementTotalExceptions();
                PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                faultError = true;
            }

            if (faultError)
            {
                HandleError();
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Shutdown()
        {
            if (_state == TcpConnectionState.Connected)
            {
                _loop.RunInLoop(() => ShutdownInLoop());
            }
        }

        /// <summary>
        /// 在事件循环线程中关闭连接
        /// </summary>
        private void ShutdownInLoop()
        {
            if (!_loop.IsInLoopThread())
            {
                throw new NetException("ShutdownInLoop should be called in loop thread");
            }

            if (!_channel.IsWriting())
            {
                try
                {
                    _socket.Shutdown(SocketShutdown.Both);
                    _state = TcpConnectionState.Disconnecting;
                }
                catch (SocketException ex)
                {
                    Logger.Error($"Socket shutdown error: {ex.Message}");
                    PerformanceCounters.IncrementNetworkExceptions();
                }
            }
        }

        /// <summary>
        /// 处理读事件
        /// </summary>
        private void HandleRead()
        {
            try
            {
                int bytesRead = _inputBuffer.ReadFromSocket(_socket);
                if (bytesRead > 0)
                {
                    // 更新性能计数器
                    PerformanceCounters.AddBytesReceived(bytesRead);
                    PerformanceCounters.UpdateConnectionStats(_name, 0, bytesRead);
                    
                    // 如果设置了协议编解码器，尝试解析协议消息
                    if (_protocolCodec != null)
                    {
                        ProcessProtocolMessages();
                    }
                    
                    // 如果没有协议编解码器或者有未处理的原始数据，调用原始消息回调
                    if (_inputBuffer.ReadableBytes > 0)
                    {
                        MessageCallback?.Invoke(this, _inputBuffer);
                    }
                }
                else if (bytesRead == 0)
                {
                    HandleClose();
                }
            }
            catch (SocketException ex)
            {
                Logger.Error($"Socket read error on connection {_name}: {ex.SocketErrorCode}", ex);
                PerformanceCounters.IncrementNetworkExceptions();
                PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                HandleError();
            }
            catch (Exception ex)
            {
                Logger.Error($"Unexpected error in HandleRead for connection {_name}", ex);
                PerformanceCounters.IncrementTotalExceptions();
                PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                HandleError();
            }
        }

        /// <summary>
        /// 处理协议消息
        /// </summary>
        private void ProcessProtocolMessages()
        {
            if (_protocolCodec == null) return;

            try
            {
                // 循环处理所有完整的消息
                while (true)
                {
                    int messageLen = _protocolCodec.CheckMessageComplete(_inputBuffer);
                    if (messageLen == -1)
                    {
                        // 没有完整消息，停止处理
                        break;
                    }

                    // 如果有消息处理器，使用处理器解析
                    if (_messageHandler != null)
                    {
                        // 尝试使用任意类型解析，需要消息处理器确定类型
                        // 这里暂时跳过原始数据，等待处理器实现
                        var headerLen = _protocolCodec.HeaderLength;
                        _inputBuffer.Retrieve(headerLen);
                        var messageData = _inputBuffer.RetrieveAsBytes(messageLen);
                        
                        // 这里需要具体的消息类型信息，目前传递null
                        // _messageHandler.HandleMessage(this, null);
                        Logger.Debug($"Received protocol message: size={messageLen} bytes");
                        PerformanceCounters.AddBytesReceived(messageLen);
                    }
                    else
                    {
                        // 没有特定的消息处理器，使用默认处理
                        // 这里也是暂时跳过，等待具体的示例实现
                        var headerLen = _protocolCodec.HeaderLength;
                        _inputBuffer.Retrieve(headerLen);
                        var messageData = _inputBuffer.RetrieveAsBytes(messageLen);
                        Logger.Debug($"Skipped unknown protocol message: size={messageLen} bytes");
                        PerformanceCounters.AddBytesReceived(messageLen);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"Error processing protocol messages on connection {_name}", ex);
                PerformanceCounters.IncrementProtocolExceptions();
                PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                // 发生错误时，清空缓冲区以防止持续出错
                _inputBuffer.Clear();
            }
        }

        /// <summary>
        /// 处理写事件
        /// </summary>
        private void HandleWrite()
        {
            if (!_loop.IsInLoopThread())
            {
                throw new NetException("HandleWrite should be called in loop thread");
            }

            if (_channel.IsWriting())
            {
                try
                {
                    int bytesWritten = _outputBuffer.WriteToSocket(_socket);
                    if (bytesWritten > 0)
                    {
                        // 更新性能计数器
                        PerformanceCounters.AddBytesSent(bytesWritten);
                        PerformanceCounters.UpdateConnectionStats(_name, bytesWritten, 0);
                        
                        if (_outputBuffer.ReadableBytes == 0)
                        {
                            _channel.DisableWriting();
                            if (WriteCompleteCallback != null)
                            {
                                _loop.QueueInLoop(() => WriteCompleteCallback(this));
                            }
                            if (_state == TcpConnectionState.Disconnecting)
                            {
                                _loop.QueueInLoop(ShutdownInLoop);
                            }
                        }
                    }
                }
                catch (SocketException ex)
                {
                    Logger.Error($"Socket write error on connection {_name}: {ex.SocketErrorCode}", ex);
                    PerformanceCounters.IncrementNetworkExceptions();
                    PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                    HandleError();
                }
                catch (Exception ex)
                {
                    Logger.Error($"Unexpected error in HandleWrite for connection {_name}", ex);
                    PerformanceCounters.IncrementTotalExceptions();
                    PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
                    HandleError();
                }
            }
        }

        /// <summary>
        /// 处理错误事件
        /// </summary>
        private void HandleError()
        {
            Logger.Warning($"TCP connection {_name} error, closing connection");
            PerformanceCounters.UpdateConnectionStats(_name, 0, 0, true);
            HandleClose();
        }

        /// <summary>
        /// 处理连接关闭
        /// </summary>
        private void HandleClose()
        {
            if (_state == TcpConnectionState.Connected || _state == TcpConnectionState.Disconnecting)
            {
                _state = TcpConnectionState.Disconnected;
                _channel.DisableAll();
                CloseCallback?.Invoke(this);
                
                // 更新性能计数器
                PerformanceCounters.DecrementActiveConnections();
                PerformanceCounters.RemoveConnectionStats(_name);
            }
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                try
                {
                    // 取消注册Socket
                    SocketManager.UnregisterSocket(_socket);
                    _socket.Close();
                }
                catch (Exception ex)
                {
                    Logger.Error($"Socket close error: {ex.Message}");
                    PerformanceCounters.IncrementNetworkExceptions();
                }
                _channel.Dispose();
            }
        }
    }
}